package com.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

import java.util.ArrayList;
import java.util.List;

public class HorizontalScrollView extends ViewGroup {
    private final Scroller mScroller;
    private int mTouchSlop;
    private int childWidth;
    private int childHeight;
    private float mDownX;
    private float mMoveX;
    private float mNewMoveX;
    private int leftBorder;
    private int rightBorder;
    private int mContentWidth;
    private int mSwitchX;
    private VelocityTracker mVelocityTracker;
    private int index;
    private Context mContext;
    private List<Integer> data = new ArrayList<>();
    private int mLastXIntercept = 0;
    private int mLastYIntercept = 0;
    private pageIndexListener mListener;
    private final String TAG = "HorizontalScrollView";

    public HorizontalScrollView(Context context) {
        this(context, null);
    }

    public HorizontalScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public HorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mScroller = new Scroller(context);
        ViewConfiguration configuration = ViewConfiguration.get(context);
        // 获取TouchSlop值
//        mTouchSlop = configuration.getScaledPagingTouchSlop() / 2;
        mVelocityTracker = VelocityTracker.obtain();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        childWidth = 0;
        childHeight = 0;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            childView.setClickable(true);
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);

            childWidth += childView.getMeasuredWidth();
            childHeight = Math.max(0, childView.getMeasuredHeight());
        }
        setMeasuredDimension(measureWidth(widthMeasureSpec, childWidth), measureHeight(heightMeasureSpec, childHeight));
        mContentWidth = getMeasuredWidth();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed) {
            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                View childView = getChildAt(i);
                childView.layout(i * getMeasuredWidth(), 0, (i + 1) * mContentWidth, childHeight);
            }
        }
        // 初始化左右边界值
        leftBorder = getChildAt(0).getLeft();
        rightBorder = getChildAt(getChildCount() - 1).getRight();
        mSwitchX = getMeasuredWidth() / 5;

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = event.getRawX();
                intercepted = false;
                break;
            case MotionEvent.ACTION_MOVE:
                mMoveX = event.getRawX();
                //                float diff = Math.abs(mMoveX - mDownX);
                //                if (diff > mTouchSlop) {
                //                    intercepted = true;
                //                }
                int deltaX = x - mLastXIntercept;
                int deltaY = y - mLastYIntercept;
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                Log.v(TAG, "list_move");
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
        }
        mDownX = mMoveX;
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mVelocityTracker.addMovement(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                mNewMoveX = event.getRawX();
                int scrollX = (int) -(mNewMoveX - mDownX);
                if (getScrollX() + scrollX < leftBorder) {
                    scrollTo(leftBorder, 0);
                    return true;
                } else if (getScrollX() + getWidth() + scrollX > rightBorder) {
                    scrollTo(rightBorder - getWidth(), 0);
                    return true;
                }
                scrollBy(scrollX, 0);
                break;
            case MotionEvent.ACTION_UP:
                int scroll = getScrollX();
                mVelocityTracker.computeCurrentVelocity(1000);
                float xVelocity = mVelocityTracker.getXVelocity();
                if (Math.abs(xVelocity) >= 100) {
                    index = xVelocity > 0 ? index - 1 : index + 1;
                } else {
                    index = (scroll + getWidth() / 2) / getWidth();
                }
                index = Math.max(0, Math.min(index, getChildCount() - 1));

                Log.v(TAG, "page_index --- " + index);
                mListener.pageIndex(index);

                int dx = index * getWidth() - scroll;
                mScroller.startScroll(getScrollX(), 0, dx, 0);
                invalidate();
                mVelocityTracker.clear();
                break;
        }
        mDownX = mNewMoveX;

        return super.onTouchEvent(event);
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }

    public interface pageIndexListener {
        void pageIndex(int pageIndex);
    }

    public void setOnIndexListener(pageIndexListener listener) {
        this.mListener = listener;
    }

    private int measureWidth(int measureSpec, int viewGroupWidth) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = specSize;
                break;
            case MeasureSpec.AT_MOST:
                /* 将剩余宽度和所有子View + padding的值进行比较，取小的作为ViewGroup的宽度 */
                result = Math.min(viewGroupWidth, specSize);
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
        }
        return result;
    }

    private int measureHeight(int measureSpec, int viewGroupHeight) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = specSize;
                break;
            case MeasureSpec.AT_MOST:
                /* 将剩余高度和所有子View + padding的值进行比较，取小的作为ViewGroup的高度 */
                result = Math.min(viewGroupHeight, specSize);
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
        }
        return result;
    }
}
